home *** CD-ROM | disk | FTP | other *** search
/ Celestin Apprentice 5 / Apprentice-Release5.iso / Source Code / Libraries / LinAlg 3.1 / LinAlg / svd.cc < prev    next >
Encoding:
Text File  |  1995-12-21  |  23.5 KB  |  624 lines  |  [TEXT/ALFA]

  1. // This may look like C code, but it is really -*- C++ -*-
  2. /*
  3.  ************************************************************************
  4.  *
  5.  *              Numerical Math Package
  6.  *    Singular Value Decomposition of a rectangular matrix
  7.  *                 A = U * Sig * V'
  8.  *
  9.  * where matrices U and V are orthogonal and Sig is a digonal matrix.
  10.  *
  11.  * The singular value decomposition is performed by constructing an SVD
  12.  * object from an M*N matrix A with M>=N (that is, at least as many rows
  13.  * as columns). Note, in case M > N, matrix Sig has to be a M*N diagonal
  14.  * matrix. However, it has only N diag elements, which we store in a 1:N
  15.  * Vector sig.
  16.  *
  17.  * Algorithm
  18.  *    Bidiagonalization with Hausholder reflections followed by a
  19.  * modification of a QR-algorithm. For more details, see
  20.  *   G.E. Forsythe, M.A. Malcolm, C.B. Moler
  21.  *   Computer methods for mathematical computations. - Prentice-Hall, 1977
  22.  * However, in the persent implementation, matrices U and V are computed
  23.  * right away rather than delayed until after all Hausholder reflections.
  24.  *
  25.  * This code is based for the most part on a Algol68 code I wrote
  26.  * ca. 1987
  27.  *
  28.  * $Id$
  29.  *
  30.  ************************************************************************
  31.  */
  32.  
  33. #ifdef __GNUC__
  34. #pragma implementation
  35. #endif
  36.  
  37. #include <math.h>
  38. #include "svd.h"
  39. #include <float.h>
  40.  
  41. /*
  42.  *------------------------------------------------------------------------
  43.  *                Bidiagonalization
  44.  */
  45.  
  46.  /*
  47.  *            Left Hausholder Transformations
  48.  *
  49.  * Zero out an entire subdiagonal of the i-th column of A and compute the
  50.  * modified A[i,i] by multiplication (UP' * A) with a matrix UP'
  51.  *   (1)  UP' = E - UPi * UPi' / beta
  52.  *
  53.  * where a column-vector UPi is as follows
  54.  *   (2)  UPi = [ (i-1) zeros, A[i,i] + Norm, vector A[i+1:M,i] ]
  55.  * where beta = UPi' * A[,i] and Norm is the norm of a vector A[i:M,i]
  56.  * (sub-diag part of the i-th column of A). Note we assign the Norm the
  57.  * same sign as that of A[i,i].
  58.  * By construction, (1) does not affect the first (i-1) rows of A. Since
  59.  * A[*,1:i-1] is bidiagonal (the result of the i-1 previous steps of
  60.  * the bidiag algorithm), transform (1) doesn't affect these i-1 columns
  61.  * either as one can easily verify.
  62.  * The i-th column of A is transformed as
  63.  *   (3)  UP' * A[*,i] = A[*,i] - UPi
  64.  * (since UPi'*A[*,i]/beta = 1 by construction of UPi and beta)
  65.  * This means effectively zeroing out A[i+1:M,i] (the entire subdiagonal
  66.  * of the i-th column of A) and replacing A[i,i] with the -Norm. Thus
  67.  * modified A[i,i] is returned by the present function.
  68.  * The other (i+1:N) columns of A are transformed as
  69.  *    (4)  UP' * A[,j] = A[,j] - UPi * ( UPi' * A[,j] / beta )
  70.  * Note, due to (2), only elements of rows i+1:M actually  participate
  71.  * in above transforms; the upper i-1 rows of A are not affected.
  72.  * As was mentioned earlier,
  73.  * (5)  beta = UPi' * A[,i] = (A[i,i] + Norm)*A[i,i] + A[i+1:M,i]*A[i+1:M,i]
  74.  *    = ||A[i:M,i]||^2 + Norm*A[i,i] = Norm^2 + Norm*A[i,i]
  75.  * (note the sign of the Norm is the same as A[i,i])
  76.  * For extra precision, vector UPi (and so is Norm and beta) are scaled,
  77.  * which would not affect (4) as easy to see.
  78.  *
  79.  * To satisfy the definition
  80.  *   (6)  .SIG = U' A V
  81.  * the result of consecutive transformations (1) over matrix A is accumulated
  82.  * in matrix U' (which is initialized to be a unit matrix). At each step,
  83.  * U' is left-multiplied by UP' = UP (UP is symmetric by construction,
  84.  * see (1)). That is, U is right-multiplied by UP, that is, rows of U are
  85.  * transformed similarly to columns of A, see eq. (4). We also keep in mind
  86.  * that multiplication by UP at the i-th step does not affect the first i-1
  87.  * columns of U.
  88.  * Note that the vector UPi doesn't have to be allocated explicitly: its
  89.  * first i-1 components are zeros (which we can always imply in computations),
  90.  * and the rest of the components (but the UPi[i]) are the same as those
  91.  * of A[i:M,i], the subdiagonal of A[,i]. This column, A[,i] is affected only
  92.  * trivially as explained above, that is, we don't need to carry this
  93.  * transformation explicitly (only A[i,i] is going to be non-trivially
  94.  * affected, that is, replaced by -Norm, but we will use sig[i] to store
  95.  * the result).
  96.  *
  97.  */
  98.  
  99.  inline double SVD::left_hausholder(Matrix& A, const int i)
  100.  {
  101.    MatrixColumn UPi(A,i);        // Note that only UPi[i:M] matter
  102.    register int j,k;
  103.    REAL scale = 0;            // Compute the scaling factor
  104.    for(k=i; k<=M; k++)
  105.      scale += abs(UPi(k));
  106.    if( scale == 0 )            // If A[,i] is a null vector, no
  107.      return 0;                // transform is required
  108.    double Norm_sqr = 0;            // Scale UPi (that is, A[,i])
  109.    for(k=i; k<=M; k++)            // and compute its norm, Norm^2
  110.      Norm_sqr += sqr(UPi(k) /= scale);
  111.    double new_Aii = sqrt(Norm_sqr);    // new_Aii = -Norm, Norm has the
  112.    if( UPi(i) > 0 ) new_Aii = -new_Aii;    // same sign as Aii (that is, UPi[i])
  113.    const float beta = - UPi(i)*new_Aii + Norm_sqr;
  114.    UPi(i) -= new_Aii;            // UPi[i] = A[i,i] - (-Norm)
  115.    
  116.    for(j=i+1; j<=N; j++)        // Transform i+1:N columns of A
  117.    {
  118.      MatrixColumn Aj(A,j);
  119.      REAL factor = 0;
  120.      for(k=i; k<=M; k++)
  121.        factor += UPi(k) * Aj(k);    // Compute UPi' * A[,j]
  122.      factor /= beta;
  123.      for(k=i; k<=M; k++)
  124.        Aj(k) -= UPi(k) * factor;
  125.    }
  126.  
  127.    for(j=1; j<=M; j++)            // Accumulate the transform in U
  128.    {
  129.      MatrixRow Uj(U,j);
  130.      REAL factor = 0;
  131.      for(k=i; k<=M; k++)
  132.        factor += UPi(k) * Uj(k);    // Compute  U[j,] * UPi
  133.      factor /= beta;
  134.      for(k=i; k<=M; k++)
  135.         Uj(k) -= UPi(k) * factor;
  136.    }
  137.    return new_Aii * scale;        // Scale new Aii back (our new Sig[i])
  138.  }
  139.  
  140. /*
  141.  *            Right Hausholder Transformations
  142.  *
  143.  * Zero out i+2:N elements of a row A[i,] of matrix A by right
  144.  * multiplication (A * VP) with a matrix VP
  145.  *   (1)  VP = E - VPi * VPi' / beta
  146.  *
  147.  * where a vector-column .VPi is as follows
  148.  *   (2)  VPi = [ i zeros, A[i,i+1] + Norm, vector A[i,i+2:N] ]
  149.  * where beta = A[i,] * VPi and Norm is the norm of a vector A[i,i+1:N]
  150.  * (right-diag part of the i-th row of A). Note we assign the Norm the
  151.  * same sign as that of A[i,i+1].
  152.  * By construction, (1) does not affect the first i columns of A. Since
  153.  * A[1:i-1,] is bidiagonal (the result of the previous steps of
  154.  * the bidiag algorithm), transform (1) doesn't affect these i-1 rows
  155.  * either as one can easily verify.
  156.  * The i-th row of A is transformed as
  157.  *  (3)  A[i,*] * VP = A[i,*] - VPi'
  158.  * (since A[i,*]*VPi/beta = 1 by construction of VPi and beta)
  159.  * This means effectively zeroing out A[i,i+2:N] (the entire right super-
  160.  * diagonal of the i-th row of A, but ONE superdiag element) and replacing
  161.  * A[i,i+1] with - Norm. Thus modified A[i,i+1] is returned as the result of
  162.  * the present function.
  163.  * The other (i+1:M) rows of A are transformed as
  164.  *    (4)  A[j,] * VP = A[j,] - VPi' * ( A[j,] * VPi / beta )
  165.  * Note, due to (2), only elements of columns i+1:N actually  participate
  166.  * in above transforms; the left i columns of A are not affected.
  167.  * As was mentioned earlier,
  168.  * (5)  beta = A[i,] * VPi = (A[i,i+1] + Norm)*A[i,i+1]
  169.  *               + A[i,i+2:N]*A[i,i+2:N]
  170.  *    = ||A[i,i+1:N]||^2 + Norm*A[i,i+1] = Norm^2 + Norm*A[i,i+1]
  171.  * (note the sign of the Norm is the same as A[i,i+1])
  172.  * For extra precision, vector VPi (and so is Norm and beta) are scaled,
  173.  * which would not affect (4) as easy to see.
  174.  *
  175.  * The result of consecutive transformations (1) over matrix A is accumulated
  176.  * in matrix V (which is initialized to be a unit matrix). At each step,
  177.  * V is right-multiplied by VP. That is, rows of V are transformed similarly
  178.  * to rows of A, see eq. (4). We also keep in mind that multiplication by
  179.  * VP at the i-th step does not affect the first i rows of V.
  180.  * Note that vector VPi doesn't have to be allocated explicitly: its
  181.  * first i components are zeros (which we can always imply in computations),
  182.  * and the rest of the components (but the VPi[i+1]) are the same as those
  183.  * of A[i,i+1:N], the superdiagonal of A[i,]. This row, A[i,] is affected
  184.  * only trivially as explained above, that is, we don't need to carry this
  185.  * transformation explicitly (only A[i,i+1] is going to be non-trivially
  186.  * affected, that is, replaced by -Norm, but we will use super_diag[i+1] to
  187.  * store the result).
  188.  *
  189.  */
  190.  
  191. inline double SVD::right_hausholder(Matrix& A, const int i)
  192. {
  193.    MatrixRow VPi(A,i);            // Note only VPi[i+1:N] matter
  194.    register int j,k;
  195.    REAL scale = 0;            // Compute the scaling factor
  196.    for(k=i+1; k<=N; k++)
  197.      scale += abs(VPi(k));
  198.    if( scale == 0 )            // If A[i,] is a null vector, no
  199.      return 0;                // transform is required
  200.  
  201.    double Norm_sqr = 0;            // Scale VPi (that is, A[i,])
  202.    for(k=i+1; k<=N; k++)        // and compute its norm, Norm^2
  203.      Norm_sqr += sqr(VPi(k) /= scale);
  204.    double new_Aii1 = sqrt(Norm_sqr);    // new_Aii1 = -Norm, Norm has the
  205.    if( VPi(i+1) > 0 )            // same sign as
  206.      new_Aii1 = -new_Aii1;         // Aii1 (that is, VPi[i+1])
  207.    const float beta = - VPi(i+1)*new_Aii1 + Norm_sqr;
  208.    VPi(i+1) -= new_Aii1;        // VPi[i+1] = A[i,i+1] - (-Norm)
  209.    
  210.    for(j=i+1; j<=M; j++)        // Transform i+1:M rows of A
  211.    {
  212.      MatrixRow Aj(A,j);
  213.      REAL factor = 0;
  214.      for(k=i+1; k<=N; k++)
  215.        factor += VPi(k) * Aj(k);    // Compute A[j,] * VPi
  216.      factor /= beta;
  217.      for(k=i+1; k<=N; k++)
  218.        Aj(k) -= VPi(k) * factor;
  219.    }
  220.  
  221.    for(j=1; j<=N; j++)            // Accumulate the transform in V
  222.    {
  223.      MatrixRow Vj(V,j);
  224.      REAL factor = 0;
  225.      for(k=i+1; k<=N; k++)
  226.        factor += VPi(k) * Vj(k);    // Compute  V[j,] * VPi
  227.      factor /= beta;
  228.      for(k=i+1; k<=N; k++)
  229.        Vj(k) -= VPi(k) * factor;
  230.    }
  231.    return new_Aii1 * scale;        // Scale new Aii1 back
  232. }
  233.  
  234. /*
  235.  *------------------------------------------------------------------------
  236.  *              Bidiagonalization
  237.  * This nethod turns matrix A into a bidiagonal one. Its N diagonal elements
  238.  * are stored in a vector sig, while N-1 superdiagonal elements are stored
  239.  * in a vector super_diag(2:N) (with super_diag(1) being always 0).
  240.  * Matrices U and V store the record of orthogonal Hausholder
  241.  * reflections that were used to convert A to this form. The method
  242.  * returns the norm of the resulting bidiagonal matrix, that is, the
  243.  * maximal column sum.
  244.  */
  245.  
  246. double SVD::bidiagonalize(Vector& super_diag, const Matrix& _A)
  247. {
  248.   double norm_acc = 0;
  249.   super_diag(1) = 0;            // No superdiag elem above A(1,1)
  250.   Matrix A = _A;            // A being transformed
  251.   A.resize_to(_A.q_nrows(),_A.q_ncols()); // Indexing from 1
  252.   for(register int i=1; i<=N; i++)
  253.   {
  254.     const REAL& diagi = sig(i) = left_hausholder(A,i);
  255.     if( i < N )
  256.       super_diag(i+1) = right_hausholder(A,i);
  257.     norm_acc = max(norm_acc,abs(diagi)+abs(super_diag(i)));
  258.   }
  259.   return norm_acc;
  260. }
  261.  
  262. /*
  263.  *------------------------------------------------------------------------
  264.  *        QR-diagonalization of a bidiagonal matrix
  265.  *
  266.  * After bidiagonalization we get a bidiagonal matrix J:
  267.  *    (1)  J = U' * A * V
  268.  * The present method turns J into a matrix JJ by applying a set of
  269.  * orthogonal transforms
  270.  *    (2)  JJ = S' * J * T
  271.  * Orthogonal matrices S and T are chosen so that JJ were also a
  272.  * bidiagonal matrix, but with superdiag elements smaller than those of J.
  273.  * We repeat (2) until non-diag elements of JJ become smaller than EPS
  274.  * and can be disregarded.
  275.  * Matrices S and T are constructed as
  276.  *    (3)  S = S1 * S2 * S3 ... Sn, and similarly T
  277.  * where Sk and Tk are matrices of simple rotations
  278.  *    (4)  Sk[i,j] = i==j ? 1 : 0 for all i>k or i<k-1
  279.  *         Sk[k-1,k-1] = cos(Phk),  Sk[k-1,k] = -sin(Phk),
  280.  *         SK[k,k-1] = sin(Phk),    Sk[k,k] = cos(Phk), k=2..N
  281.  * Matrix Tk is constructed similarly, only with angle Thk rather than Phk.
  282.  *
  283.  * Thus left multiplication of J by SK' can be spelled out as
  284.  *    (5)  (Sk' * J)[i,j] = J[i,j] when i>k or i<k-1,
  285.  *                  [k-1,j] = cos(Phk)*J[k-1,j] + sin(Phk)*J[k,j]
  286.  *                  [k,j] =  -sin(Phk)*J[k-1,j] + cos(Phk)*J[k,j]
  287.  * That is, k-1 and k rows of J are replaced by their linear combinations;
  288.  * the rest of J is unaffected. Right multiplication of J by Tk similarly
  289.  * changes only k-1 and k columns of J.
  290.  * Matrix T2 is chosen the way that T2'J'JT2 were a QR-transform with a
  291.  * shift. Note that multiplying J by T2 gives rise to a J[2,1] element of
  292.  * the product J (which is below the main diagonal). Angle Ph2 is then
  293.  * chosen so that multiplication by S2' (which combines 1 and 2 rows of J)
  294.  * gets rid of that elemnent. But this will create a [1,3] non-zero element.
  295.  * T3 is made to make it disappear, but this leads to [3,2], etc.
  296.  * In the end, Sn removes a [N,N-1] element of J and matrix S'JT becomes
  297.  * bidiagonal again. However, because of a special choice
  298.  * of T2 (QR-algorithm), its non-diag elements are smaller than those of J.
  299.  *
  300.  * All this process in more detail is described in
  301.  *    J.H. Wilkinson, C. Reinsch. Linear algebra - Springer-Verlag, 1971
  302.  *
  303.  * If during transforms (1), JJ[N-1,N] turns 0, then JJ[N,N] is a singular
  304.  * number (possibly with a wrong (that is, negative) sign). This is a
  305.  * consequence of Frantsis' Theorem, see the book above. In that case, we can
  306.  * eliminate the N-th row and column of JJ and carry out further transforms
  307.  * with a smaller matrix. If any other superdiag element of JJ turns 0,
  308.  * then JJ effectively falls into two independent matrices. We will process
  309.  * them independently (the bottom one first).
  310.  *
  311.  * Since matrix J is a bidiagonal, it can be stored efficiently. As a matter
  312.  * of fact, its N diagonal elements are in array Sig, and superdiag elements
  313.  * are stored in array super_diag.
  314.  */
  315.  
  316.                 // Carry out U * S with a rotation matrix
  317.                 // S (which combines i-th and j-th columns
  318.                 // of U, i>j)
  319. inline void SVD::rotate(Matrix& U, const int i, const int j,
  320.            const double cos_ph, const double sin_ph)
  321. {
  322.   MatrixColumn Ui(U,i), Uj(U,j);
  323.   for(register int l=1; l<=U.q_row_upb(); l++)
  324.   {
  325.     REAL& Uil = Ui(l); REAL& Ujl = Uj(l);
  326.     const REAL Ujl_was = Ujl;
  327.     Ujl =  cos_ph*Ujl_was + sin_ph*Uil;
  328.     Uil = -sin_ph*Ujl_was + cos_ph*Uil;
  329.   }
  330. }
  331.  
  332. /*
  333.  * A diagonal element J[l-1,l-1] turns out 0 at the k-th step of the
  334.  * algorithm. That means that one of the original matrix' singular numbers
  335.  * shall be zero. In that case, we multiply J by specially selected
  336.  * matrices S' of simple rotations to eliminate a superdiag element J[l-1,l].
  337.  * After that, matrix J falls into two pieces, which can be dealt with
  338.  * in a regular way (the bottom piece first).
  339.  * 
  340.  * These special S transformations are accumulated into matrix U: since J
  341.  * is left-multiplied by S', U would be right-multiplied by S. Transform
  342.  * formulas for doing these rotations are similar to (5) above. See the
  343.  * book cited above for more details.
  344.  */
  345. inline void SVD::rip_through(
  346.     Vector& super_diag, const int k, const int l, const double eps)
  347. {
  348.   double cos_ph = 0, sin_ph = 1;    // Accumulate cos,sin of Ph
  349.                   // The first step of the loop below
  350.                   // (when i==l) would eliminate J[l-1,l],
  351.                   // which is stored in super_diag(l)
  352.                   // However, it gives rise to J[l-1,l+1]
  353.                   // and J[l,l+2]
  354.                   // The following steps eliminate these
  355.                   // until they fall below
  356.                   // significance
  357.   for(register int i=l; i<=k; i++)
  358.   {
  359.     const double f = sin_ph * super_diag(i);
  360.     super_diag(i) *= cos_ph;
  361.     if( f <= eps )
  362.       break;            // Current J[l-1,l] became unsignificant
  363.     cos_ph = sig(i); sin_ph = -f;    // unnormalized sin/cos
  364.     const double norm = (sig(i) = hypot(cos_ph,sin_ph)); // sqrt(sin^2+cos^2)
  365.     cos_ph /= norm, sin_ph /= norm;    // Normalize sin/cos
  366.     rotate(U,i,l-1,cos_ph,sin_ph);
  367.   }
  368. }
  369.  
  370.             // We're about to proceed doing QR-transforms
  371.             // on a (bidiag) matrix J[1:k,1:k]. It may happen
  372.             // though that the matrix splits (or can be
  373.             // split) into two independent pieces. This function
  374.             // checks for splitting and returns the lowerbound
  375.             // index l of the bottom piece, J[l:k,l:k]
  376. inline int SVD::get_submatrix_to_work_on(
  377.     Vector& super_diag, const int k, const double eps)
  378. {
  379.   for(register int l=k; l>1; l--)
  380.     if( abs(super_diag(l)) <= eps )
  381.       return l;                // The breaking point: zero J[l-1,l]
  382.     else if( abs(sig(l-1)) <= eps )    // Diagonal J[l,l] turns out 0
  383.     {                    // meaning J[l-1,l] _can_ be made
  384.       rip_through(super_diag,k,l,eps);    // zero after some rotations
  385.       return l;
  386.     }
  387.   return 1;            // Deal with J[1:k,1:k] as a whole
  388. }
  389.  
  390.         // Diagonalize root module
  391. void SVD::diagonalize(Vector& super_diag, const double eps)
  392. {
  393.   for(register int k=N; k>=1; k--)    // QR-iterate upon J[l:k,l:k]
  394.   {
  395.     register int l;
  396.     while(l=get_submatrix_to_work_on(super_diag,k,eps),
  397.           abs(super_diag(k)) > eps)    // until superdiag J[k-1,k] becomes 0
  398.     {
  399.       double shift;            // Compute a QR-shift from a bottom
  400.       {                    // corner minor of J[l:k,l:k] order 2
  401.           REAL Jk2k1 = super_diag(k-1),    // J[k-2,k-1]
  402.                Jk1k  = super_diag(k),
  403.                Jk1k1 = sig(k-1),        // J[k-1,k-1]
  404.                Jkk   = sig(k),
  405.                Jll   = sig(l);        // J[l,l]
  406.           shift = (Jk1k1-Jkk)*(Jk1k1+Jkk) + (Jk2k1-Jk1k)*(Jk2k1+Jk1k);
  407.           shift /= 2*Jk1k*Jk1k1;
  408.           shift += (shift < 0 ? -1 : 1) * sqrt(shift*shift+1);
  409.           shift = ( (Jll-Jkk)*(Jll+Jkk) + Jk1k*(Jk1k1/shift-Jk1k) )/Jll;
  410.       }
  411.                       // Carry on multiplications by T2, S2, T3...
  412.       double cos_th = 1, sin_th = 1;
  413.       REAL Ji1i1 = sig(l);    // J[i-1,i-1] at i=l+1...k
  414.       for(register int i=l+1; i<=k; i++)
  415.       {
  416.           REAL Ji1i = super_diag(i), Jii = sig(i);  // J[i-1,i] and J[i,i]
  417.           sin_th *= Ji1i; Ji1i *= cos_th; cos_th = shift;
  418.           double norm_f = (super_diag(i-1) = hypot(cos_th,sin_th));
  419.           cos_th /= norm_f, sin_th /= norm_f;
  420.                           // Rotate J[i-1:i,i-1:i] by Ti
  421.           shift = cos_th*Ji1i1 + sin_th*Ji1i;    // new J[i-1,i-1]
  422.           Ji1i = -sin_th*Ji1i1 + cos_th*Ji1i;    // J[i-1,i] after rotation
  423.           const double Jii1 = Jii*sin_th;        // Emerged J[i,i-1]
  424.           Jii *= cos_th;                // new J[i,i]
  425.         rotate(V,i,i-1,cos_th,sin_th); // Accumulate T rotations in V
  426.         
  427.         double cos_ph = shift, sin_ph = Jii1;// Make Si to get rid of J[i,i-1]
  428.         sig(i-1) = (norm_f = hypot(cos_ph,sin_ph));    // New J[i-1,i-1]
  429.         if( norm_f == 0 )        // If norm =0, rotation angle
  430.           cos_ph = cos_th, sin_ph = sin_th; // can be anything now
  431.         else
  432.           cos_ph /= norm_f, sin_ph /= norm_f;
  433.                           // Rotate J[i-1:i,i-1:i] by Si
  434.         shift = cos_ph * Ji1i + sin_ph*Jii;    // New J[i-1,i]
  435.         Ji1i1 = -sin_ph*Ji1i + cos_ph*Jii;    // New Jii, would carry over
  436.                             // as J[i-1,i-1] for next i
  437.         rotate(U,i,i-1,cos_ph,sin_ph);  // Accumulate S rotations in U
  438.                         // Jii1 disappears, sin_th would
  439.         cos_th = cos_ph, sin_th = sin_ph; // carry over a (scaled) J[i-1,i+1]
  440.                         // to eliminate on the next i, cos_th
  441.                         // would carry over a scaled J[i,i+1]
  442.       }
  443.       super_diag(l) = 0;        // Supposed to be eliminated by now
  444.       super_diag(k) = shift;
  445.       sig(k) = Ji1i1;
  446.     }        // --- end-of-QR-iterations
  447.     if( sig(k) < 0 )        // Correct the sign of the sing number
  448.     {
  449.       sig(k) = -sig(k);
  450.       MatrixColumn Vk(V,k);
  451.       for(register int j=1; j<=V.q_row_upb(); j++)
  452.         Vk(j) = -Vk(j);
  453.     }
  454.   }
  455.     
  456.  
  457.  
  458. /*
  459.  *------------------------------------------------------------------------
  460.  *                The root Module
  461.  */
  462.  
  463. SVD::SVD(const Matrix& A)
  464.    : M(A.q_nrows()), N(A.q_ncols()),
  465.      U(A.q_nrows(),A.q_nrows()),
  466.      V(A.q_ncols(),A.q_ncols()),
  467.      sig(A.q_ncols())
  468. {
  469.   if( M < N )
  470.     A.info(),
  471.     _error("Matrix A should have at least as many rows as it has columns");
  472.      
  473.   U.unit_matrix(); V.unit_matrix();
  474.  
  475.   Vector super_diag(N);
  476.   const double bidiag_norm = bidiagonalize(super_diag,A);
  477.   const double eps = FLT_EPSILON * bidiag_norm;    // Significance threshold
  478.   diagonalize(super_diag,eps);
  479. }
  480.  
  481. /*
  482.  *------------------------------------------------------------------------
  483.  *        Print some info about the SVD that has been built
  484.  */
  485.  
  486.                 // Print the info about the SVD
  487. void SVD::info(void) const
  488. {
  489.   U.is_valid();
  490.   message("\nSVD of an %dx%d matrix",M,N);
  491. }
  492.  
  493.                 // Return min and max singular values
  494. SVD::operator MinMax(void) const
  495. {
  496.   REAL max_sig, min_sig;
  497.   max_sig = min_sig = sig(1);
  498.   for(register int i=2; i<=sig.q_no_elems(); i++)
  499.     if( sig(i) > max_sig )
  500.       max_sig = sig(i);
  501.     else if( sig(i) < min_sig )
  502.       min_sig = sig(i);
  503.   return MinMax(min_sig,max_sig);
  504. }
  505.  
  506.                     // sig_max/sig_min
  507. double SVD::q_cond_number(void) const
  508. {
  509.   return ((MinMax)(*this)).ratio();
  510. }
  511.  
  512. /*
  513.  *------------------------------------------------------------------------
  514.  *             class SVD_inv_mult
  515.  *     Solving an (overspecified) set of linear equations A*X=B
  516.  *         using a least squares method via SVD
  517.  *
  518.  * Matrix A is a rectangular M*N matrix with M>=N, B is a M*K matrix
  519.  * with K either =1 (that is, B is merely a column-vector) or K>1.
  520.  * If B is a unit matrix of the size that of A, the present LazyMatrix is
  521.  * a regularized (pseudo)inverse of A.
  522.  *
  523.  * Algorithm
  524.  *   Matrix A is decomposed first using SVD:
  525.  *    (1) A = U*Sig*V'
  526.  * where matrices U and V are orthogonal and Sig is diagonal.
  527.  * The set of simultaneous linear equations AX=B can be written then as
  528.  *    (2) Sig*V'*X = U'*B
  529.  * (where we have used the fact that U'=inv(U)), or
  530.  *    (3) Sig*Vx = Ub
  531.  * where we introduced
  532.  *    (4) Vx = V'*X and Ub = U'*b
  533.  * Since Sig is a diag matrix, eq. (3) is solved trivially:
  534.  *     (5) Vx[i] = Ub[i]/sig[i], if sig[i] > tau
  535.  *          = 0    otherwise
  536.  * In the latter case matrix Sig has an incomplete rank, or close to that.
  537.  * That is, one or more singular values are _too_ small. This means that
  538.  * there is linear dependence among the equations of the set. In that case,
  539.  * we will print the corresponding "null coefficients", the corresponding
  540.  * columns of V. Adding them to the solution X won't change A*X.
  541.  *
  542.  * Having computed Vx, X is simply recovered as
  543.  *    (6) X = V*Vx
  544.  * since V*V' = E.
  545.  *
  546.  * Threshold tau in (5) is chosen as N*FLT_EPSILON*max(Sig[i,i]) unless
  547.  * specified otherwise by the user.
  548.  */
  549.  
  550. SVD_inv_mult::SVD_inv_mult
  551.     (const SVD& _svd, const Matrix& _B,const double _tau)
  552.     : LazyMatrix(_svd.q_V().q_ncols(),_B.q_ncols()),
  553.       svd(_svd), B(_B), tau(_tau)
  554. {
  555.   if( svd.q_U().q_nrows() != B.q_nrows() )
  556.     svd.info(), B.info(),
  557.     _error("Unsuitable matrices for SVD*X=B set");
  558.   MinMax sig_minmax = (MinMax)svd;
  559.   if( tau == 0 )
  560.    tau = svd.q_V().q_nrows() * sig_minmax.max() * FLT_EPSILON;
  561.   are_zero_coeff = sig_minmax.min() < tau;
  562. }
  563.  
  564. #if 0
  565.                 // Computing X in a special case where
  566.                 // B (and X) is a vector
  567. inline void SVD_inv_mult::fill_in_vector(Matrix& X) const
  568. {
  569.   X.clear();
  570.   bool x_is_vector = x.q_ncols() == 1;
  571.   if( are_zero_coeff )
  572.     message("\nSVD solver of AX=B detected a linear dependency among X"
  573.             "\n  #  \tsingular value\tnull coefficients\n");
  574.   for(register int i=1; i<=svd.q_V().q_nrows(); i++)
  575.   {
  576.      MatrixCol Ui(U,i);
  577.      const double sigi = svd.q_sig()(i);
  578.      if( sigi > tau )
  579.        if( x_is_vector )
  580.          X(i) = (Ui * B)/sigi;
  581.        else
  582.          X(i) =0, print null coeffs...
  583.   }
  584.   X *= V;            // ???
  585. }
  586. #endif
  587.                 // Computing X in a general case where
  588.                 // B (and X) is a rectangular matrix
  589. void SVD_inv_mult::fill_in(Matrix& X) const
  590. {
  591.   if( are_zero_coeff )
  592.     message("\nSVD solver of AX=B detected a linear dependency among X"
  593.             "\n  #  singular value\tnull coefficients\n");
  594.   Matrix Vx(Matrix::Zero,X);
  595.   Vector Ui(svd.q_U().q_nrows());            // i-th col of U
  596.   Vector Bj(B.q_nrows());                // j-th col of B
  597.   Vector Vxi(X.q_ncols());                // i-th row of VX
  598.   const Matrix& V = svd.q_V();
  599.   const Matrix& U = svd.q_U();
  600.  
  601.   for(register int i=1; i<=V.q_ncols(); i++)
  602.   {
  603.     const double sigi = svd.q_sig()(i);
  604.     if( sigi > tau )
  605.     {
  606.       Ui = MatrixColumn(U,i);
  607.       for(register int j=1; j<=X.q_ncols(); j++)
  608.         Bj = MatrixColumn(B,j), Vxi(j) = Ui * Bj/sigi;
  609.      }
  610.      else
  611.      {
  612.       Vxi = 0;
  613.       message(" %d %12.2g \t(",i,sigi);
  614.       for(register int j=1; j<=V.q_nrows(); j++)
  615.         message("%10g ",V(j,i));
  616.       message(")\n");
  617.     }
  618.     MatrixRow(Vx,i) = Vxi;
  619.   }
  620.   X.mult(V,Vx);                // that is, set X to be V*Vx
  621. }
  622.  
  623.